<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Helios Demo – Latest Blocks</title>

    <!-- Helios bundle & ethers -->
    <script src="./dist/lib.umd.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ethers/5.7.2/ethers.umd.min.js"></script>

    <style>
      /* ---------- Layout ---------- */
      html,
      body {
        height: 100%;
        margin: 0;
      }
      body {
        font-family: Arial, Helvetica, sans-serif;
        display: flex;
        flex-direction: column;
        color: #333;
      }

      h1,
      h2 {
        color: #ff8800;
        margin: 0 0 0.3rem 0;
      }
      .header {
        padding: 10px 25px;
      }

      /* ---------- Panel grid ---------- */
      .panels-container {
        flex: 1 1 auto;
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 20px;
        padding: 0 20px 20px;
        box-sizing: border-box;
      }
      @media (max-width: 900px) {
        .panels-container {
          grid-template-columns: 1fr;
        }
      }

      /* ---------- Card ---------- */
      .panel {
        border: 1px solid #ddd;
        border-radius: 6px;
        padding: 24px;
        display: flex;
        flex-direction: column;
        background: #fafafa;
        min-height: 260px;
      }

      /* ---------- Block read‑out ---------- */
      .block-info {
        position: relative;
        overflow: hidden;
        background: #f4f4f4;
        border-radius: 6px;
        font-size: 22px;
        line-height: 1.4;
        padding: 20px 18px;
        margin: 0;
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        text-align: center;
        white-space: pre-line;
      }
      .block-number {
        color: #ff8800;
        font-weight: 700;
        font-size: 1.8em;
      }

      /* ---------- Loading wheel ---------- */
      .loading:before {
        content: "";
        width: 32px;
        height: 32px;
        border: 4px solid #ff8800;
        border-top-color: transparent;
        border-radius: 50%;
        animation: spin 1s linear infinite;
      }
      @keyframes spin {
        to {
          transform: rotate(360deg);
        }
      }

      /* ---------- Loading bar (bottom, 12 px) ---------- */
      .block-info.animate::after {
        content: "";
        position: absolute;
        left: 0;
        bottom: 0;
        width: 100%;
        height: 12px;
        background: #ff8800;
        opacity: 0.6;
        transform-origin: left;
        transform: scaleX(0);
        animation: loadBar var(--duration, 2s) linear forwards;
        pointer-events: none;
      }
      @keyframes loadBar {
        to {
          transform: scaleX(1);
        }
      }

      /* ---------- Opacity flash on update ---------- */
      .block-info.flash {
        animation: flashOpacity 0.8s ease-out;
      }
      @keyframes flashOpacity {
        0% {
          opacity: 0.25;
        }
        100% {
          opacity: 1;
        }
      }
    </style>
  </head>
  <body>
    <!-- ---------- Header ---------- -->
    <div class="header">
      <h1>Helios Demo</h1>
      <p><em>Fast, secure &amp; portable multichain light client</em></p>
    </div>

    <!-- ---------- Panels ---------- -->
    <div class="panels-container">
      <div class="panel">
        <h2>Ethereum</h2>
        <pre class="block-info loading" id="ethereum-latest"></pre>
      </div>
      <div class="panel">
        <h2>OP Mainnet</h2>
        <pre class="block-info loading" id="op-mainnet-latest"></pre>
      </div>
      <div class="panel">
        <h2>Base</h2>
        <pre class="block-info loading" id="base-latest"></pre>
      </div>
      <div class="panel">
        <h2>Linea</h2>
        <pre class="block-info loading" id="linea-latest"></pre>
      </div>
    </div>

    <!-- ---------- Script ---------- -->
    <script>
      // Build display string for a block
      function formatBlock(block) {
        const ts = new Date(block.timestamp * 1000);
        const date = ts.toLocaleDateString();
        const time = ts.toLocaleTimeString([], {
          hour: "2-digit",
          minute: "2-digit",
          second: "2-digit",
        });
        const txCount = block.transactions.length;
        const txLabel = txCount === 1 ? "transaction" : "transactions";
        return `<span class="block-number">Block ${block.number}</span><br>${date} ${time}<br>${txCount} ${txLabel}`;
      }

      // Render a block and start animations
      function renderBlock(network, blockTime, block) {
        const el = document.getElementById(`${network}-latest`);
        el.classList.remove("loading");
        el.innerHTML = formatBlock(block);
        el.style.setProperty("--duration", `${blockTime}s`);
        el.classList.remove("animate", "flash");
        void el.offsetWidth;
        el.classList.add("animate", "flash");
      }

      (async () => {
        const key = "<ALCHEMY_KEY>";

        window.networks = [
          {
            name: "ethereum",
            blockTime: 12,
            cfg: {
              executionRpc: `https://eth-mainnet.g.alchemy.com/v2/${key}`,
              checkpoint:
                "0x872dbe854d76a78fd22c8c7f2e157467a1604f585785e5e6fbbc2987c1b1980e",
              dbType: "localstorage",
            },
            kind: "ethereum",
          },
          {
            name: "op-mainnet",
            blockTime: 2,
            cfg: {
              executionRpc: `https://opt-mainnet.g.alchemy.com/v2/${key}`,
              network: "op-mainnet",
            },
            kind: "opstack",
          },
          {
            name: "base",
            blockTime: 2,
            cfg: {
              executionRpc: `https://base-mainnet.g.alchemy.com/v2/${key}`,
              network: "base",
            },
            kind: "opstack",
          },
          {
            name: "linea",
            blockTime: 3,
            cfg: {
              executionRpc: `https://linea-mainnet.g.alchemy.com/v2/${key}`,
              network: "mainnet",
            },
            kind: "linea",
          },
        ];

        // Create providers for each network and attach ethers provider
        await Promise.all(
          window.networks.map((n) =>
            (async () => {
              n.provider = await helios.createHeliosProvider(n.cfg, n.kind);
              n.ethers = new ethers.providers.Web3Provider(n.provider);
            })()
          )
        );

        // Poll for latest blocks
        window.networks.forEach((n) => {
          setInterval(async () => {
            try {
              const latestNumber = await n.ethers.getBlockNumber();
              if (latestNumber !== n.lastSeen) {
                n.lastSeen = latestNumber;
                const blk = await n.ethers.getBlock(latestNumber);
                renderBlock(n.name, n.blockTime, blk);
              }
            } catch (err) {
              console.error(`Error fetching ${n.name}:`, err);
            }
          }, 1000);
        });
      })();
    </script>
  </body>
</html>
